package redis.clients.jedis;

import java.util.List;
import java.util.Set;

public interface MultiKeyCommands {
	Long del(String... keys);

	Long exists(String... keys);

	List<String> blpop(int timeout, String... keys);

	List<String> brpop(int timeout, String... keys);

	List<String> blpop(String... args);

	List<String> brpop(String... args);

	/**
	 * Returns all the keys matching the glob-style pattern. For example if you have
	 * in the database the keys "foo" and "foobar" the command "KEYS foo*" will
	 * return "foo foobar".<br>
	 * <strong>Warning:</strong> consider this as a command that should be used in
	 * production environments with <strong>extreme care</strong>. It may ruin
	 * performance when it is executed against large databases. This command is
	 * intended for debugging and special operations, such as changing your keyspace
	 * layout. <strong>Don't use it in your regular application code.</strong> If
	 * you're looking for a way to find keys in a subset of your keyspace, consider
	 * using {@link #scan(String, ScanParams)} or sets.
	 * <p>
	 * While the time complexity for this operation is O(N), the constant times are
	 * fairly low. For example, Redis running on an entry level laptop can scan a 1
	 * million key database in 40 milliseconds.
	 * <p>
	 * Glob style patterns examples:
	 * <ul>
	 * <li>h?llo will match hello hallo hhllo
	 * <li>h*llo will match hllo heeeello
	 * <li>h[ae]llo will match hello and hallo, but not hillo
	 * </ul>
	 * <p>
	 * Use \ to escape special chars if you want to match them verbatim.
	 * <p>
	 * Time complexity: O(n) (with n being the number of keys in the DB, and
	 * assuming keys and pattern of limited length)
	 * 
	 * @param pattern
	 * @return Multi bulk reply
	 * @see <a href="https://redis.io/commands/keys">Redis KEYS documentation</a>
	 */
	Set<String> keys(String pattern);

	List<String> mget(String... keys);

	String mset(String... keysvalues);

	Long msetnx(String... keysvalues);

	String rename(String oldkey, String newkey);

	Long renamenx(String oldkey, String newkey);

	String rpoplpush(String srckey, String dstkey);

	Set<String> sdiff(String... keys);

	Long sdiffstore(String dstkey, String... keys);

	Set<String> sinter(String... keys);

	Long sinterstore(String dstkey, String... keys);

	Long smove(String srckey, String dstkey, String member);

	Long sort(String key, SortingParams sortingParameters, String dstkey);

	Long sort(String key, String dstkey);

	Set<String> sunion(String... keys);

	Long sunionstore(String dstkey, String... keys);

	String watch(String... keys);

	String unwatch();

	Long zinterstore(String dstkey, String... sets);

	Long zinterstore(String dstkey, ZParams params, String... sets);

	Long zunionstore(String dstkey, String... sets);

	Long zunionstore(String dstkey, ZParams params, String... sets);

	String brpoplpush(String source, String destination, int timeout);

	Long publish(String channel, String message);

	void subscribe(JedisPubSub jedisPubSub, String... channels);

	void psubscribe(JedisPubSub jedisPubSub, String... patterns);

	String randomKey();

	Long bitop(BitOP op, final String destKey, String... srcKeys);

	@Deprecated
	/**
	 * @see #scan(String, ScanParams)
	 */
	ScanResult<String> scan(int cursor);

	ScanResult<String> scan(final String cursor);

	/**
	 * Iterates the set of keys in the currently selected Redis database.
	 * <p>
	 * Since this command allows for incremental iteration, returning only a small
	 * number of elements per call, it can be used in production without the
	 * downside of commands like {@link #keys(String)} or
	 * {@link JedisCommands#smembers(String)} )} that may block the server for a
	 * long time (even several seconds) when called against big collections of keys
	 * or elements.
	 * <p>
	 * SCAN basic usage<br>
	 * SCAN is a cursor based iterator. This means that at every call of the
	 * command, the server returns an updated cursor that the user needs to use as
	 * the cursor argument in the next call. An iteration starts when the cursor is
	 * set to 0, and terminates when the cursor returned by the server is 0.
	 * <p>
	 * Scan guarantees<br>
	 * The SCAN command, and the other commands in the SCAN family, are able to
	 * provide to the user a set of guarantees associated to full iterations.
	 * <ul>
	 * <li>A full iteration always retrieves all the elements that were present in
	 * the collection from the start to the end of a full iteration. This means that
	 * if a given element is inside the collection when an iteration is started, and
	 * is still there when an iteration terminates, then at some point SCAN returned
	 * it to the user.
	 * <li>A full iteration never returns any element that was NOT present in the
	 * collection from the start to the end of a full iteration. So if an element
	 * was removed before the start of an iteration, and is never added back to the
	 * collection for all the time an iteration lasts, SCAN ensures that this
	 * element will never be returned.
	 * </ul>
	 * However because SCAN has very little state associated (just the cursor) it
	 * has the following drawbacks:
	 * <ul>
	 * <li>A given element may be returned multiple times. It is up to the
	 * application to handle the case of duplicated elements, for example only using
	 * the returned elements in order to perform operations that are safe when
	 * re-applied multiple times.
	 * <li>Elements that were not constantly present in the collection during a full
	 * iteration, may be returned or not: it is undefined.
	 * </ul>
	 * <p>
	 * Time complexity: O(1) for every call. O(N) for a complete iteration,
	 * including enough command calls for the cursor to return back to 0. N is the
	 * number of elements inside the DB.
	 *
	 * @param cursor
	 *            The cursor.
	 * @param params
	 *            the scan parameters. For example a glob-style match pattern
	 * @return the scan result with the results of this iteration and the new
	 *         position of the cursor
	 * @see <a href="https://redis.io/commands/scan">Redis SCAN documentation</a>
	 */
	ScanResult<String> scan(final String cursor, final ScanParams params);

	String pfmerge(final String destkey, final String... sourcekeys);

	long pfcount(final String... keys);
}
